/**
*@brief 实现串口类
*发送或接受的数据均使用uchar[]形式，默认发送字节数为8
*示例
* int fd;
* fd_set fs_read;
* struct termios option;
* char myport[] =  "/dev/ttyUSB0";
* 
* //串口初始化*********************************************
* CSerialPort myserialport(fd,option,myport,fs_read);      //向串口类传入参数
* myserialport.openPort();                                 //打开串口 
* myserialport.setPort();                                  //串口设置
* myserialport.writeToCom_char((char*)&send_data,sizeof(send_data));
*/
#include "CSerialPort.h"

using namespace std;

CSerialPort::CSerialPort()
{
    FILE *fp;
    const char *cmd = "ls /dev/ttyUSB*";
    const char *type = "r";
    char buffer[14];
    int device_number = 0;
    //搜索串口设备号,重连串口
    memset(buffer, '\0', sizeof(buffer));
    fp = popen(cmd, type);
    fread(buffer, sizeof(char), 12, fp);
    if (buffer[1] == 'd')
    {
        device_number = buffer[11] - 48;
    }
    pclose(fp);
    m_com = buffer;

    openPort();
    setPort();
}

CSerialPort::~CSerialPort()
{
    closePort();
}

void CSerialPort::openPort()
{

    m_fd = open(m_com, O_RDWR | O_NOCTTY | O_NDELAY); //非堵塞情况

    if (m_fd == -1)
    {
        perror("openPort: Unable to open COM");
    }
}

void CSerialPort::closePort()
{
    close(m_fd);
}

void CSerialPort::setPort()
{
    tcgetattr(m_fd, &m_option);
    /*修改所获得的参数*/
    m_option.c_cflag |= (CLOCAL | CREAD); //设置控制模式状态，本地连接，接收使能
    m_option.c_cflag &= ~CSIZE;           //字符长度，设置数据位之前一定要屏掉这个位
    m_option.c_cflag &= ~CRTSCTS;         //无硬件流控
    m_option.c_cflag |= CS8;              //8位数据长度
    m_option.c_cflag &= ~CSTOPB;          //1位停止位
    m_option.c_iflag |= IGNPAR;           //无奇偶检验位
    m_option.c_oflag = 0;                 //输出模式
    m_option.c_lflag = 0;                 //不激活终端模式
    cfsetospeed(&m_option, B115200);      //设置波特率
    cfsetispeed(&m_option, B115200);      //设置波特率

    m_option.c_iflag &= ~(IXON | IXOFF | IXANY);

    m_option.c_cc[VTIME] = 0;
    m_option.c_cc[VMIN] = 0;

    /*设置新属性，TCSANOW：所有改变立即生效*/
    tcflush(m_fd, TCIFLUSH); //溢出数据可以接收，但不读
    tcsetattr(m_fd, TCSANOW, &m_option);
}


/**
 * @brief 向串口写数据
 * @param data 符号字符数组
 * @param datalen 数组长度
 * 
 */

int CSerialPort::writeToCom_char(char *data, int datalen)
{
    int len = 0;
    len = write(m_fd, data, datalen); //实际写入的长度

    if (len != datalen) //写入不成功
    {
        FILE *fp;
        const char *cmd = "ls /dev/ttyUSB*";
        const char *type = "r";
        char buffer[14];
        int device_number = 0;
        //搜索串口设备号,重连串口
        memset(buffer, '\0', sizeof(buffer));
        fp = popen(cmd, type);
        fread(buffer, sizeof(char), 12, fp);
        if (buffer[1] == 'd')
        {
            device_number = buffer[11] - 48;
        }
        pclose(fp);
        m_com = buffer;
        cout << m_com << endl;
        closePort();
        openPort();
        setPort();
    }
    else
    {
        printf("send data success.\n");
    }
}

/**
 * @brief 从串口读数据
 * @param data 符号字符数组
 * @param datalen 数组长度
 * 
 */

int CSerialPort::readFromCom_uchar(unsigned char *data, int datalen)
{
    int len = 0;
    len = read(m_fd, data, datalen);
    return len;
}

